package com.dog.basics.service.common.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Validator;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.digest.DigestUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dog.basics.bean.dto.admin.common.AdminDogComFileInfoFromDto;
import com.dog.basics.bean.dto.admin.common.AdminSonDogComFileInfoFromDto;
import com.dog.basics.bean.model.common.DogComFileInfo;
import com.dog.basics.bean.vo.admin.common.AdminComFileInfosVo;
import com.dog.basics.bean.vo.admin.common.AdminDogComFileInfoVo;
import com.dog.basics.bean.vo.api.common.ApiComFileInfoUploadVo;
import com.dog.basics.bean.vo.api.common.ApiComFileInfosVo;
import com.dog.basics.common.constant.ComFileInfoConstant;
import com.dog.basics.common.constant.CommonConstants;
import com.dog.basics.common.photooss.properties.UploadUtilProperties;
import com.dog.basics.common.photooss.service.PhotoOssUtil;
import com.dog.basics.common.photooss.util.MinioUtil;
import com.dog.basics.common.properties.FileProperties;
import com.dog.basics.common.util.FileNameUtils;
import com.dog.basics.common.util.FileUtils;
import com.dog.basics.common.util.PageParam;
import com.dog.basics.common.util.SpringContextUtils;
import com.dog.basics.dao.common.DogComFileInfoMapper;
import com.dog.basics.service.common.IDogComFileInfoService;
import lombok.AllArgsConstructor;
import lombok.SneakyThrows;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 文件信息表 服务实现类
 * </p>
 *
 * @author YC
 * @since 2021-02-22
 */
@Service
@AllArgsConstructor
public class DogComFileInfoServiceImpl extends ServiceImpl<DogComFileInfoMapper, DogComFileInfo> implements IDogComFileInfoService {

    private final FileProperties fileProperties;

    private final UploadUtilProperties uploadUtilProperties;

    /**
     * @Description: 分页
     * @Param: status
     * @return: IPage
     * @Author: cy
     * @Date:
     */
    @Override
    public IPage<AdminDogComFileInfoVo> getPageList(PageParam page, AdminDogComFileInfoFromDto obj) {
        // 查询分页数据
        return this.baseMapper.getPageList(page, obj);
    }


    /**
     * 子页面分页查询
     *
     * @param page 分页对象
     * @param obj  文件信息表
     * @return
     */
    @Override
    public IPage<AdminDogComFileInfoVo> getSonPageList(PageParam page, AdminSonDogComFileInfoFromDto obj) {
        DogComFileInfo dogNews = this.getById(obj.getIndexSonId());
        if (ObjectUtil.isNull(dogNews)) {
            return null;

        }
        this.page(page, Wrappers.<DogComFileInfo>lambdaQuery()
                .eq(ObjectUtil.isNotNull(dogNews.getFileMdFileMdfive()), DogComFileInfo::getFileMdFileMdfive, dogNews.getFileMdFileMdfive())
                .eq(ObjectUtil.isNotNull(obj.getFileType()), DogComFileInfo::getFileType, obj.getFileType())
                .eq(ObjectUtil.isNotNull(obj.getFileState()), DogComFileInfo::getFileState, obj.getFileState())
                .like(StrUtil.isNotBlank(obj.getFileName()), DogComFileInfo::getFileName, obj.getFileName())
                .orderBy(Boolean.TRUE, obj.getIsOrderByAvg(), DogComFileInfo::getCreateTime));
        List<DogComFileInfo> records = page.getRecords();
        page.setRecords(records.stream().map(e -> {
            AdminDogComFileInfoVo newsVo = new AdminDogComFileInfoVo();
            BeanUtil.copyProperties(e, newsVo);
            return newsVo;
        }).collect(Collectors.toList()));
        return page;
    }

    /**
     * @Description: 查询详情
     * @Param: obj
     * @return: Boolean
     * @Author: cy
     * @Date: 2020/05/19  0027
     */
    @Override
    public AdminDogComFileInfoVo getObjXq(Long id) {
        DogComFileInfo dogNews = this.getById(id);
        Validator.validateNotNull(dogNews, "common.noData");
        return BeanUtil.toBean(dogNews, AdminDogComFileInfoVo.class);
    }

    /**
     * @param business_id 业务标识
     * @param classTable  所属表
     * @return
     * @功能描述: 查询项目中文件信息
     * @author He
     * @date 2021/2/22
     */
    @Override
    public List<ApiComFileInfosVo> getApiComFileInfos(Long business_id, String classTable) {
        // 查询数据信息
        List<DogComFileInfo> fileInfos = this.list(Wrappers.<DogComFileInfo>lambdaQuery().eq(DogComFileInfo::getFileBusinessId, business_id).eq(DogComFileInfo::getFileClassTable, classTable));
        // 数据格式化
        return fileInfos.stream().map(e -> BeanUtil.toBean(e, ApiComFileInfosVo.class)).collect(Collectors.toList());
    }

    /**
     * @param business_id 业务标识admin
     * @param classTable  所属表
     * @return
     * @功能描述: 查询项目中文件信息
     * @author He
     * @date 2021/2/22
     */
    @Override
    public List<AdminComFileInfosVo> getAdminComFileInfos(Long business_id, String classTable) {
        // 查询数据信息
        List<DogComFileInfo> fileInfos = this.list(Wrappers.<DogComFileInfo>lambdaQuery().eq(DogComFileInfo::getFileBusinessId, business_id).eq(DogComFileInfo::getFileClassTable, classTable));
        // 数据格式化
        return fileInfos.stream().map(e -> BeanUtil.toBean(e, AdminComFileInfosVo.class)).collect(Collectors.toList());
    }

    /**
     * @功能描述: API-上传业务文件
     * @author He
     * @date 2021/2/22
     */
    @Override
    @SneakyThrows
    public List<ApiComFileInfoUploadVo> addApiComFileInfoUpload(List<MultipartFile> file, List<String> aliasNames) {
        // 判断文件是否有文件信息
        Validator.validateTrue(CollUtil.isNotEmpty(file), "file.noData");
        for (int i = 0; i < file.size(); i++) {
            Validator.validateFalse(file.isEmpty(), "file.noData");
        }
        // 判断是否有别名、并且别名需要限制
        if (CollUtil.isNotEmpty(aliasNames)) {
            // 判断别名长度是否一致
            Validator.validateEqual(file.size(), aliasNames.size(), "file.name.num");
            // 判断别名字段长度是否受限制
            for (int i = 0; i < aliasNames.size(); i++) {
                Validator.validateTrue((aliasNames.get(i).length() <= 200), "file.name");
            }
        }
        // 循环处理上传信息
        List<DogComFileInfo> fileInfos = CollUtil.newArrayList();
        for (int i = 0; i < file.size(); i++) {
            //先判断MD5是否存在
            String fileMdFileMdfive = DigestUtil.md5Hex(file.get(i).getInputStream());
            List<DogComFileInfo> list = this.list(Wrappers.<DogComFileInfo>lambdaQuery().eq(DogComFileInfo::getFileMdFileMdfive, fileMdFileMdfive).orderByAsc(DogComFileInfo::getCreateTime).last(" limit 1"));
            DogComFileInfo fileInfo = new DogComFileInfo();
            if (CollUtil.isNotEmpty(list)) {
                // 数据信息拷贝
                BeanUtil.copyProperties(list.get(0),fileInfo,"fileId","fileClassTable","fileState","updateTime","updateUser");
                // 数据信息格式化
                fileInfo.setFileExplainName(CollUtil.isNotEmpty(aliasNames) ? aliasNames.get(i) : fileInfo.getFileName());
                fileInfo.setFileBusinessId(CommonConstants.DEFAULT_VAL_LONG);
                fileInfo.setCreateUser(CommonConstants.DEFAULT_VAL_LONG);
                fileInfo.setCreateTime(DateUtil.currentSeconds());
                fileInfos.add(fileInfo);
            } else {
                fileInfo.setOriginalName(file.get(i).getOriginalFilename());
                fileInfo.setFileMdFileMdfive(fileMdFileMdfive);
                fileInfo.setFileSize(file.get(i).getSize());
                fileInfo.setFileHead(DateUtil.format(cn.hutool.core.date.DateUtil.date(), "yyyy/MM/dd"));
                if (Validator.equal(uploadUtilProperties.getUploadType(), CommonConstants.QINIUOSS)) {
                    fileInfo.setFilePath(SpringContextUtils.getBean("qiniuPhotoOssUtil", PhotoOssUtil.class).uploadFile(file.get(i), null, fileInfo.getFileHead(), null));
                    fileInfo.setFileType(4);
                } else if (Validator.equal(uploadUtilProperties.getUploadType(), CommonConstants.ALIYUNOSS)) {
                    fileInfo.setFilePath(SpringContextUtils.getBean("aliyunPhotoOssUtil", PhotoOssUtil.class).uploadFile(file.get(i), null, fileInfo.getFileHead(), null));
                    fileInfo.setFileType(3);
                } else if (Validator.equal(uploadUtilProperties.getUploadType(), CommonConstants.MINIO)) {
                    fileInfo.setFilePath(MinioUtil.upload(file.get(i), fileInfo.getFileHead()));
                    fileInfo.setFileType(1);
                } else {
                    fileInfo.setFilePath(StrUtil.format("{}/{}", fileInfo.getFileHead(), FileNameUtils.getFileName(FileNameUtils.getSuffix(file.get(i).getOriginalFilename()))));
                    //判断上传是否成功
                    if (Validator.isFalse(FileUtils.upload(file.get(i), fileProperties.url(), fileInfo.getFilePath()))) {
                        fileInfo.setFilePath(null);
                        fileInfo.setFileType(0);
                    }
                }
                // 判断是否添加成功
                if (StrUtil.isNotBlank(fileInfo.getFilePath())) {
                    // 封装数据信息
                    fileInfo.setFileClassTable(CommonConstants.DEFAULT_VAL_LONG.toString());
                    fileInfo.setFileName(FileNameUtils.getFileNameByName(fileInfo.getFilePath()));
                    fileInfo.setFileSuffix(FileNameUtils.getSuffix(file.get(i).getOriginalFilename()));
                    fileInfo.setFileExplainName(CollUtil.isNotEmpty(aliasNames) ? aliasNames.get(i) : fileInfo.getFileName());
                    fileInfo.setFileSource(ComFileInfoConstant.FILESOURCEOTHER);
                    fileInfo.setFileBusinessId(CommonConstants.DEFAULT_VAL_LONG);
                    fileInfo.setCreateUser(CommonConstants.DEFAULT_VAL_LONG);
                    fileInfo.setCreateTime(DateUtil.currentSeconds());
                    fileInfos.add(fileInfo);
                } else {
                    // 先删除文件
                    delUploadFileInfo(fileInfos);
                    // 后通知结果
                    Validator.validateTrue(Boolean.FALSE, "file.upload");
                }

            }

        }
        // 文件信息添加
        if (CollUtil.isNotEmpty(fileInfos)) {
            if (!this.saveBatch(fileInfos)) {
                // 先删除文件
                delUploadFileInfo(fileInfos);
                // 后通知结果
                Validator.validateTrue(Boolean.FALSE, "file.upload");
            }
        }
        // 格式化数据返回信息
        return fileInfos.stream().map(e -> BeanUtil.toBean(e, ApiComFileInfoUploadVo.class)).collect(Collectors.toList());
    }

    /**
     * @param fileIds        使用的文件ids数组标识
     * @param businessId     业务标识
     * @param classTableName 使用业务表名 SYS_USER
     * @return
     * @功能描述: 修改未使用的文件关联业务 (内部)
     * @author He
     * @date 2021/2/23
     */
    @Override
    public Boolean editNotUsedComFileInfo(List<Long> fileIds, Long businessId, String classTableName) {
        // 判断会否为空
        if (CollUtil.isNotEmpty(fileIds)) {
            // 处理未使用的文件 - 并且未关联业务
            Integer fileSuccessCount = this.baseMapper.editNotUsedComFileInfo(fileIds, businessId, classTableName, DateUtil.currentSeconds());
            if (retBool(fileSuccessCount)) {
                return Boolean.TRUE;
            }
        }
        return Boolean.FALSE;
    }

    /**
     * @param fileIds        使用的文件ids数组标识
     * @param businessId     业务标识
     * @param classTableName 使用业务表名 SYS_USER
     * @return
     * @功能描述: 删除(修改删除的) 添加(修改添加的) (内部)
     * @author He
     * @date 2021年3月18日
     */
    @Override
    public Boolean editDelUsedAddNotUsed(List<Long> fileIds, Long businessId, String classTableName) {
        // 先查询已使用
        List<DogComFileInfo> fileInfos = this.list(Wrappers.<DogComFileInfo>lambdaQuery().eq(DogComFileInfo::getFileBusinessId, businessId).eq(DogComFileInfo::getFileClassTable, classTableName));
        // 判断是否需要做处理
        if (CollUtil.isNotEmpty(fileInfos)) {

            // 声明接收处理的id
            List<Long> ids = CollUtil.newArrayList();
            for (int i = 0; i < fileInfos.size(); i++) {
                Integer count = this.count(Wrappers.<DogComFileInfo>lambdaQuery().eq(DogComFileInfo::getFileMdFileMdfive, fileInfos.get(i).getFileMdFileMdfive()));
                // 判断是否包含此元素
                if (fileIds.contains(fileInfos.get(i).getFileId())) {
                    fileIds.remove(fileInfos.get(i).getFileId());
                } else {
                    if(count>1){
                        // 删除数据库
                        ids.add(fileInfos.get(i).getFileId());
                    }else{
                        // 删除数据库
                        ids.add(fileInfos.get(i).getFileId());
                        // 删除文件
                        delUploadFileInfo(CollUtil.newArrayList(fileInfos.get(i)));
                    }
                }
            }
            // 删除已作废的文件
            if (CollUtil.isNotEmpty(ids)) {
                this.removeByIds(ids);
            }
        }
        // 判断是否为空
        if (CollUtil.isNotEmpty(fileIds)) {
            this.editNotUsedComFileInfo(fileIds, businessId, classTableName);
        }
        return Boolean.TRUE;
    }


    /**
     * 删除多余文件信息 (内部调用)
     */
    public Boolean delUploadFileInfo(List<DogComFileInfo> fileInfos) {
        // 循环删除文件信息
        for (int i = 0; i < fileInfos.size(); i++) {
            if (Validator.equal(uploadUtilProperties.getUploadType(), CommonConstants.QINIUOSS)) {
                SpringContextUtils.getBean("qiniuPhotoOssUtil", PhotoOssUtil.class).deleteFile(fileInfos.get(i).getFilePath(), null);
            } else if (Validator.equal(uploadUtilProperties.getUploadType(), CommonConstants.ALIYUNOSS)) {
                SpringContextUtils.getBean("aliyunPhotoOssUtil", PhotoOssUtil.class).deleteFile(fileInfos.get(i).getFilePath(), null);
            } else if (Validator.equal(uploadUtilProperties.getUploadType(), CommonConstants.MINIO)) {
                MinioUtil.removeObject(fileInfos.get(i).getFilePath(), null);
            } else {
                FileUtils.removeFile(fileProperties.url(), fileInfos.get(i).getFilePath());
            }
        }
        return Boolean.TRUE;
    }

    /**
     * @Description: 删除
     * @Param: ids
     * @return: Boolean
     * @Author: cy
     * @Date: 2020/05/19  0027
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteObj(Long id) {
        DogComFileInfo dogNews = this.getById(id);
        Validator.validateNotNull(dogNews, "common.noData");
        //通过MD5查询 看看是否有多个文件
        Integer count = this.count(Wrappers.<DogComFileInfo>lambdaQuery().eq(DogComFileInfo::getFileMdFileMdfive, dogNews.getFileMdFileMdfive()));
        if (count>1) {
            Validator.validateTrue(this.removeById(id), "common.del");
        } else {
            List<DogComFileInfo> fileInfos = CollUtil.newArrayList(dogNews);
            Validator.validateTrue(this.delUploadFileInfo(fileInfos), "common.del");
            Validator.validateTrue(this.removeById(id), "common.del");
        }
        return Boolean.TRUE;
    }
}
